home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 1 / QRZ Ham Radio Callsign Database - December 1993.iso / ucsd / packet / tcpip / amiga / asrc29k.lha / icmp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-08  |  6.1 KB  |  258 lines

  1. /* Internet Control Message Protocol */
  2. #include <stdio.h>
  3. #include "global.h"
  4. #include "mbuf.h"
  5. #include "internet.h"
  6. #include "timer.h"
  7. #include "iface.h"
  8. #include "ip.h"
  9. #include "icmp.h"
  10. #include "netuser.h"
  11. #include "tcp.h"
  12.  
  13. struct mib_entry Icmp_mib[] = {
  14.     "",            0,
  15.     "icmpInMsgs",        0,
  16.     "icmpInErrors",        0,
  17.     "icmpInDestUnreachs",    0,
  18.     "icmpInTimeExcds",    0,
  19.     "icmpInParmProbs",    0,
  20.     "icmpInSrcQuenchs",    0,
  21.     "icmpInRedirects",    0,
  22.     "icmpInEchos",        0,
  23.     "icmpInEchoReps",    0,
  24.     "icmpInTimestamps",    0,
  25.     "icmpInTimestampReps",    0,
  26.     "icmpInAddrMasks",    0,
  27.     "icmpInAddrMaskReps",    0,
  28.     "icmpOutMsgs",        0,
  29.     "icmpOutErrors",    0,
  30.     "icmpOutDestUnreachs",    0,
  31.     "icmpOutTimeExcds",    0,
  32.     "icmpOutParmProbs",    0,
  33.     "icmpOutSrcQuenchs",    0,
  34.     "icmpOutRedirects",    0,
  35.     "icmpOutEchos",        0,
  36.     "icmpOutEchoReps",    0,
  37.     "icmpOutTimestamps",    0,
  38.     "icmpOutTimestampReps",    0,
  39.     "icmpOutAddrMasks",    0,
  40.     "icmpOutAddrMaskReps",    0,
  41. };
  42.  
  43. /* Process an incoming ICMP packet */
  44. void
  45. icmp_input(bp,ip,rxbroadcast)
  46. struct mbuf *bp;    /* Pointer to ICMP message */
  47. struct ip *ip;
  48. int rxbroadcast;
  49. {
  50.     struct mbuf *tbp;
  51.     struct icmp icmp;    /* ICMP header */
  52.     struct ip oip;        /* Offending datagram header */
  53.     int16 type;        /* Type of ICMP message */
  54.     int16 length;
  55.  
  56.     icmpInMsgs++;
  57.     if(rxbroadcast){
  58.         /* Broadcast ICMP packets are to be IGNORED !! */
  59.         icmpInErrors++;
  60.         free_p(bp);
  61.         return;
  62.     }
  63.     length = ip->length - IPLEN - ip->optlen;
  64.     if(cksum(NULLHEADER,bp,length) != 0){
  65.         /* Bad ICMP checksum; discard */
  66.         icmpInErrors++;
  67.         free_p(bp);
  68.         return;
  69.     }
  70.     ntohicmp(&icmp,&bp);
  71.  
  72.     /* Process the message. Some messages are passed up to the protocol
  73.      * module for handling, others are handled here.
  74.      */
  75.     type = icmp.type;
  76.     
  77.     switch(uchar(type)){
  78.     case ICMP_TIME_EXCEED:    /* Time-to-live Exceeded */
  79.     case ICMP_DEST_UNREACH:    /* Destination Unreachable */
  80.     case ICMP_QUENCH:    /* Source Quench */
  81.         switch(uchar(type)){
  82.         case ICMP_TIME_EXCEED:    /* Time-to-live Exceeded */
  83.             icmpInTimeExcds++;
  84.             break;
  85.         case ICMP_DEST_UNREACH:    /* Destination Unreachable */
  86.             icmpInDestUnreachs++;
  87.             break;
  88.         case ICMP_QUENCH:    /* Source Quench */
  89.             icmpInSrcQuenchs++;
  90.             break;
  91.         }
  92.         ntohip(&oip,&bp);    /* Extract offending IP header */
  93.         if(Icmp_trace){
  94.             printf("ICMP from %s:",inet_ntoa(ip->source));
  95.             printf(" dest %s %s",inet_ntoa(oip.dest),
  96.              smsg(Icmptypes,ICMP_TYPES,uchar(type)));
  97.             switch(uchar(type)){
  98.             case ICMP_TIME_EXCEED:
  99.                 printf(" %s\n",
  100.                  smsg(Exceed,NEXCEED,uchar(icmp.code)));
  101.                 break;
  102.             case ICMP_DEST_UNREACH:
  103.                 printf(" %s\n",
  104.                  smsg(Unreach,NUNREACH,uchar(icmp.code)));
  105.                 break;
  106.             default:
  107.                 printf(" %u\n",uchar(icmp.code));
  108.                 break;
  109.             }
  110.         }
  111.         switch(uchar(oip.protocol)){
  112.         case TCP_PTCL:
  113.             tcp_icmp(oip.source,oip.dest,icmp.type,icmp.code,&bp);
  114.             break;
  115.         }
  116.         break;
  117.     case ICMP_ECHO:        /* Echo Request */
  118.         /* Change type to ECHO_REPLY, recompute checksum,
  119.          * and return datagram.
  120.          */
  121.         icmpInEchos++;
  122.         icmp.type = ICMP_ECHO_REPLY;
  123.         if((tbp = htonicmp(&icmp,bp)) == NULLBUF){
  124.             free_p(bp);
  125.             return;
  126.         }
  127.         icmpOutEchoReps++;
  128.         ip_send(ip->dest,ip->source,ICMP_PTCL,ip->tos,0,tbp,length,0,0);
  129.         return;
  130.     case ICMP_REDIRECT:    /* Redirect */
  131.         icmpInRedirects++;
  132.         break;
  133.     case ICMP_PARAM_PROB:    /* Parameter Problem */
  134.         icmpInParmProbs++;
  135.         break;
  136.     case ICMP_ECHO_REPLY:    /* Echo Reply */
  137.         icmpInEchoReps++;
  138.         echo_proc(ip->source,ip->dest,&icmp,bp);
  139.         bp = NULLBUF;    /* so it won't get freed */
  140.         break;
  141.     case ICMP_TIMESTAMP:    /* Timestamp */
  142.         icmpInTimestamps++;
  143.         break;
  144.     case ICMP_TIME_REPLY:    /* Timestamp Reply */
  145.         icmpInTimestampReps++;
  146.         break;
  147.     case ICMP_INFO_RQST:    /* Information Request */
  148.         break;
  149.     case ICMP_INFO_REPLY:    /* Information Reply */
  150.         break;
  151.     }
  152.     free_p(bp);
  153. }
  154. /* Return an ICMP response to the sender of a datagram.
  155.  * Unlike most routines, the callER frees the mbuf.
  156.  */
  157. int
  158. icmp_output(ip,data,type,code,args)
  159. struct ip *ip;        /* Header of offending datagram */
  160. struct mbuf *data;    /* Data portion of datagram */
  161. char type,code;        /* Codes to send */
  162. union icmp_args *args;
  163. {
  164.     struct mbuf *bp;
  165.     struct icmp icmp;    /* ICMP protocol header */
  166.     int16 dlen;        /* Length of data portion of offending pkt */
  167.     int16 length;        /* Total length of reply */
  168.  
  169.     if(ip == NULLIP)
  170.         return -1;
  171.     if(uchar(ip->protocol) == ICMP_PTCL){
  172.         /* Peek at type field of ICMP header to see if it's safe to
  173.          * return an ICMP message
  174.          */
  175.         switch(uchar(data->data[0])){
  176.         case ICMP_ECHO_REPLY:
  177.         case ICMP_ECHO:
  178.         case ICMP_TIMESTAMP:
  179.         case ICMP_TIME_REPLY:
  180.         case ICMP_INFO_RQST:
  181.         case ICMP_INFO_REPLY:
  182.             break;    /* These are all safe */
  183.         default:
  184.             /* Never send an ICMP error message about another
  185.              * ICMP error message!
  186.              */
  187.             return -1;
  188.         }
  189.     }
  190.     /* Compute amount of original datagram to return.
  191.      * We return the original IP header, and up to 8 bytes past that.
  192.      */
  193.     dlen = min(8,len_p(data));
  194.     length = dlen + ICMPLEN + IPLEN + ip->optlen;
  195.     /* Take excerpt from data portion */
  196.     if(data != NULLBUF && dup_p(&bp,data,0,dlen) == 0)
  197.         return -1;    /* The caller will free data */
  198.  
  199.     /* Recreate and tack on offending IP header */
  200.     if((data = htonip(ip,bp,1)) == NULLBUF){
  201.         free_p(bp);
  202.         icmpOutErrors++;
  203.         return -1;
  204.     }
  205.     icmp.type = type;
  206.     icmp.code = code;
  207.     icmp.args.unused = 0;
  208.     switch(uchar(icmp.type)){
  209.     case ICMP_PARAM_PROB:
  210.         icmpOutParmProbs++;
  211.         icmp.args.pointer = args->pointer;
  212.         break;
  213.     case ICMP_REDIRECT:
  214.         icmpOutRedirects++;
  215.         icmp.args.address = args->address;
  216.         break;
  217.     case ICMP_ECHO:
  218.         icmpOutEchos++;
  219.         break;
  220.     case ICMP_ECHO_REPLY:
  221.         icmpOutEchoReps++;
  222.         break;
  223.     case ICMP_INFO_RQST:
  224.         break;
  225.     case ICMP_INFO_REPLY:
  226.         break;
  227.     case ICMP_TIMESTAMP:
  228.         icmpOutTimestamps++;
  229.         break;
  230.     case ICMP_TIME_REPLY:
  231.         icmpOutTimestampReps++;
  232.         icmp.args.echo.id = args->echo.id;
  233.         icmp.args.echo.seq = args->echo.seq;
  234.         break;
  235.     case ICMP_ADDR_MASK:
  236.         icmpOutAddrMasks++;
  237.         break;
  238.     case ICMP_ADDR_MASK_REPLY:
  239.         icmpOutAddrMaskReps++;
  240.         break;
  241.     case ICMP_DEST_UNREACH:
  242.         icmpOutDestUnreachs++;
  243.         break;
  244.     case ICMP_TIME_EXCEED:
  245.         icmpOutTimeExcds++;
  246.         break;
  247.     case ICMP_QUENCH:
  248.         icmpOutSrcQuenchs++;
  249.         break;
  250.     }
  251.     /* Now stick on the ICMP header */
  252.     if((bp = htonicmp(&icmp,data)) == NULLBUF){
  253.         free_p(data);
  254.         return -1;
  255.     }
  256.     return ip_send(INADDR_ANY,ip->source,ICMP_PTCL,ip->tos,0,bp,length,0,0);
  257. }
  258.